#ifndef FILESYSTEM_H
#define FILESYSTEM_H

#include <LinkedList.h>
#include <Resource.h>
#include <ResourceManager.h>
#include <File.h>

/**
   The type of an expanded file path.
**/
typedef LinkedList<char *> PathList;

/**
  Syscall interface.
**/
namespace Filesystem_IF
{
  const int traverse          =1;
  const int mknod             =2;
  const int setRoot           =3;
}

/**
  A mountable file system.
**/
class Filesystem : public Callable
{
public:

  Filesystem(char *ident, class Directory *root) :
    ident(ident), root(root)
  {
    // Initialise the resource and functions.
    resource = new Resource((Callable*)this);
    resource->add((Resource::Call1)&Filesystem::traverseResource, Filesystem_IF::traverse);
    resource->add((Resource::Call4)&Filesystem::mknod, Filesystem_IF::mknod);
    resource->add((Resource::Call1)&Filesystem::setRootResource, Filesystem_IF::setRoot);
  }
  

  ~Filesystem()
  {
    // TODO: delete root;
    delete resource;
  }
  
  /**
    Return a string containing the filesystem description.
  **/
  char *identify()
  {
    return ident;
  }
  
  /**
     Traverse the filesystem, trying to find the path specified and
     returning the File associated with it, or NULL otherwise.
  **/
  class File *traverse(char *path);
  u32int traverseResource(char *path);
  
  /**
     Transform a path,relative or absolute, given as a String, 
     into an ordered list of node names, which is minimal 
     (no ../.). None of these node names are checked to exist
     - the path may be invalid.
  **/
  PathList expandPath(char *path);

  /**
    Get the root directory
  **/
  class Directory *getRoot()
  {
    return root;
  }
  
  u32int mknod(FileTypes type, char *name, u32int resourceId, u32int impl);
  
  /**
    Set the root directory
  **/
  void setRoot(class Directory *d)
  {
    root = d;
  }
  void setRootResource(u32int r)
  {
    root = (Directory*)resourceManager.request(r)->getTarget();
  }
  
  Resource *resource;
  
protected:
  /**
    The root directory of this filesystem.
  **/
  class Directory *root;

  /**
    A null-terminated string describing this filesystem.
  **/
  char *ident;
  
};

#endif // FILESYSTEM_H
